/*
 * @Author: qinuoyun
 * @Date:   2019-11-02 11:35:39
 * @Last Modified by:   sean
 * @Last Modified time: 2019-12-27 16:06:09
 */

import md5 from 'js-md5';

/**
 * 判断是否为数组
 * @param  {[type]}  o [description]
 * @return {Boolean}   [description]
 */
export function isArray(o) {
    return Object.prototype.toString.call(o) == '[object Array]';
}

export function empty(value) {
    switch (typeof value) {
        case 'string':
            if (value == null || value == "") {
                return true
            } else {
                return false;
            }
            break;
        case 'object':
            if (value === null || Object.keys(value).length === 0) {
                return true;
            } else {
                return false;
            }
            break;
        case 'function':
            return false;
            break;
        case 'boolean':
            return !value;
            break;
        case 'number':
            if (value === NaN) {
                return true;
            } else {
                return false;
            }
            break;
        case 'null':
        case 'undefined':
        default:
            return true;
    }
    if ((value.length === 0 || value === null || value === '' || value === undefined || value === false) || Object.keys(value).length === 0) {
        return false;
    } else {
        return true;
    }
}

/**
 * 判断是否为数组
 * @param  {[type]}  o [description]
 * @return {Boolean}   [description]
 */
export function getShift(data, is_error = false) {
    if (data) {
        return Object.keys(data).shift();
    } else {
        return false;
    }
}


/**
 * 判断是否为对象
 * @param  {[type]}  data [description]
 * @return {Boolean}      [description]
 */
export function isObject(data) {
    const object = Object.prototype.toString;
    if (object.call(data) == "[object Object]") {
        return true;
    } else {
        return false;
    }
}

/**
 * 事件绑定
 * @param {any} element  绑定dom
 * @param {any} event    事件类型
 * @param {any} listener 方法
 */
export function addEvent(element, event, listener, bubble = false) {
    if (element.addEventListener) {
        element.addEventListener(event, listener, bubble);
    } else if (element.attachEvent) {
        element.attachEvent('on' + event, listener);
    } else {
        element['on' + event] = listener;
    }
}

/**
 * 获取实例化
 * @return {[type]} [description]
 */
export function getInstance(component, props = {}, data = {}, parent = null, el = null) {
    let instance = new component({
        propsData: props,
        parent: parent,
        data() {
            return data;
        },
        el: el ? el : document.createElement('div')
    })
    return instance;
}


/**
 * 深度拷贝
 * @param  {[type]} obj   [description]
 * @param  {Array}  cache [description]
 * @return {[type]}       [description]
 */
export function deepCopy(obj, cache = []) {
    // just return if obj is immutable value
    if (obj === null || typeof obj !== 'object') {
        return obj
    }

    // if obj is hit, it is in circular structure
    const hit = find(cache, c => c.original === obj)
    if (hit) {
        return hit.copy
    }

    const copy = Array.isArray(obj) ? [] : {}
    // put the copy into cache at first
    // because we want to refer it in recursive deepCopy
    cache.push({
        original: obj,
        copy
    })

    Object.keys(obj).forEach(key => {
        copy[key] = deepCopy(obj[key], cache)
    })

    return copy
}

/**
 * 正向存储
 * @param  {[type]} array [description]
 * @return {[type]}       [description]
 */
export async function forward(obj, cache = []) {
    //  判断如果为或者不为对象则直接返回
    if (obj === null || typeof obj !== 'object') {
        return obj
    }

    // 判断存在 则拷贝数据返回
    const hit = find(cache, c => c.original === obj)
    if (hit) {
        return hit.copy
    }
    const copy = Array.isArray(obj) ? [] : {}

    cache.push({
        original: obj,
        copy
    })
    Object.keys(obj).forEach(async key => {
        switch (key) {
            case 'components':
                if (typeof obj[key] === "function") {
                    let returned = obj[key]();
                    let resource = await returned.then((data) => {
                        return data.default ? data.default : data;
                    })
                    copy[key] = md5(resource.__file ? resource.__file : "");
                } else {
                    copy[key] = md5(obj[key].__file ? obj[key].__file : "");
                }
                break;
            default:
                copy[key] = await forward(obj[key], cache)
        }

    })
    return copy
}



/**
 * 反向解析
 * @param  {[type]} array [description]
 * @return {[type]}       [description]
 */
export function reverse(obj, library, cache = []) {
    //  判断如果为或者不为对象则直接返回
    if (obj === null || typeof obj !== 'object') {
        return obj
    }

    // 判断存在 则拷贝数据返回
    const hit = find(cache, c => c.original === obj)
    if (hit) {
        return hit.copy
    }
    const copy = Array.isArray(obj) ? [] : {}

    cache.push({
        original: obj,
        copy
    })
    let _handle, _tool = "";
    Object.keys(obj).forEach(key => {
        switch (key) {
            case 'components':
                _handle = obj[key];
                copy[key] = library[_handle] ? library[_handle] : "";
                break;
            default:
                copy[key] = reverse(obj[key], library, cache)
        }

    })
    return copy
}